
表D.6中列出的特征可以从其他类型构建类型。

\begin{table}[H]
	\begin{center}
	\begin{tabular}{l|l}
		\hline
		\textbf{特征}                                    & \textbf{作用}                                                \\ \hline
		remove\_const\textless{}T \textgreater{}          & 对应无const的类型                               \\ \hline
		remove\_volatile\textless{}T \textgreater{}       & 对应无volatile的类型                            \\ \hline
		remove\_cv\textless{}T \textgreater{}             & 对应无const和volatile的类型                  \\ \hline
		add\_const\textless{}T \textgreater{}             & 对应有const的类型                                       \\ \hline
		add\_volatile\textless{}T \textgreater{}          & 对应有volatile的类型                                    \\ \hline
		add\_cv\textless{}T \textgreater{}                & 对应有const volatile的类型                              \\ \hline
		make\_signed\textless{}T \textgreater{}           & 对应的有符号非引用类型                         \\ \hline
		make\_unsigned\textless{}T \textgreater{}         & 对应的无符号非引用类型                       \\ \hline
		remove\_reference\textless{}T \textgreater{}      & 对应的非引用类型                                \\ \hline
		add\_lvalue\_reference\textless{}T \textgreater{} & 对应的左值引用类型(右值变成左值)   \\ \hline
		add\_rvalue\_reference\textless{}T \textgreater{} & 对应的右值引用类型(左值保持不变)   \\ \hline
		remove\_pointer\textless{}T \textgreater{}        & 指针的引用类型(其他类型相同)               \\ \hline
		add\_pointer\textless{}T \textgreater{}           & 指向对应非引用类型的指针类型             \\ \hline
		remove\_extent\textless{}T \textgreater{}         & 数组的元素类型(其他类型相同)                 \\ \hline
		remove\_all\_extents\textless{}T \textgreater{}   & 多维数组的元素类型(其他类型相同) \\ \hline
		decay\textless{}T \textgreater{}                  & 转换为对应的“值”类型                     \\ \hline
	\end{tabular}
	\end{center}
\end{table}

\begin{center}
表D.6. 类型构造的特性
\end{center}

\textbf{std::remove\_const<T>::type}

\textbf{std::remove\_volatile<T>::type}

\textbf{std::remove\_cv<T>::type}

\begin{itemize}
\item
生成不带const或/和volatile的T类型。

\item
const指针是const限定类型，而非const指针或指向const类型的引用则不是const限定类型。例如:

\begin{lstlisting}[style=styleCXX]
remove_cv_t<int> // yields int
remove_const_t<int const> // yields int
remove_cv_t<int const volatile> // yields int
remove_const_t<int const&> // yields int const& (only refers to int const)
\end{lstlisting}

类型构造特征的顺序很重要:

\begin{tcolorbox}[colback=webgreen!5!white,colframe=webgreen!75!black]
\hspace*{0.75cm}由于这个原因，C++17后的下一个标准可能会提供remove\_refcv特性。
\end{tcolorbox}

\begin{lstlisting}[style=styleCXX]
remove_const_t<remove_reference_t<int const&>> // yields int
remove_reference_t<remove_const_t<int const&>> // yields int const
\end{lstlisting}

相反，我们可能更喜欢使用std::decay<>，但它会将数组和函数类型转换成相应的指针类型(见第D.4节):

\begin{lstlisting}[style=styleCXX]
decay_t<int const&> // yields int
\end{lstlisting}

\item
参见19.3.2节了解实现细节。
\end{itemize}

\textbf{std::add\_const<T>::type}

\textbf{std::add\_volatile<T>::type}

\textbf{std::add\_cv<T>::type}

\begin{itemize}
\item
生成在带有const或/和volatile限定符的T类型。

\item
将这些特征应用于引用类型或函数类型无效。例如:
\begin{lstlisting}[style=styleCXX]
add_cv_t<int> // yields int const volatile
add_cv_t<int const> // yields int const volatile
add_cv_t<int const volatile> // yields int const volatile
add_const_t<int> // yields int const
add_const_t<int const> // yields int const
add_const_t<int&> // yields int&
\end{lstlisting}
\end{itemize}

\textbf{std::make\_signed<T>::type}

\textbf{std::make\_unsigned<T>::type}

\begin{itemize}
\item
生成对应的有符号/无符号T类型。

\item
T是枚举类型，或除bool以外的整型(cv限定)。所有其他类型都会导致未定义行为(参见第19.7.1节，讨论如何避免这种未定义行为)。

\item
将这些特征应用于引用类型或函数类型无效，而非const指针或对const类型的引用不由const限定。例如:
\begin{lstlisting}[style=styleCXX]
make_unsigned_t<char> // yields unsigned char
make_unsigned_t<int> // yields unsigned int
make_unsigned_t<int const&> // undefined behavior
\end{lstlisting}
\end{itemize}

\textbf{std::remove\_reference<T>::type}

\begin{itemize}
\item
生成引用类型T引用的类型(若T不是引用类型，则生成T本身)。

\item
例如:
\begin{lstlisting}[style=styleCXX]
remove_reference_t<int> // yields int
remove_reference_t<int const> // yields int const
remove_reference_t<int const&> // yields int const
remove_reference_t<int&&> // yields int
\end{lstlisting}

\item
引用类型本身不是const类型。因此，类型构造特征的顺序很重要:

\begin{tcolorbox}[colback=webgreen!5!white,colframe=webgreen!75!black]
\hspace*{0.75cm}由于这个原因，C++17后的下一个标准可能会提供remove\_refcv特性。
\end{tcolorbox}

\begin{lstlisting}[style=styleCXX]
remove_const_t<remove_reference_t<int const&>> // yields int
remove_reference_t<remove_const_t<int const&>> // yields int const
\end{lstlisting}

相反，我们可能更喜欢使用std::decay<>，但会将数组和函数类型转换成相应的指针类型(见第D.4节):

\begin{lstlisting}[style=styleCXX]
decay_t<int const&> // yields int
\end{lstlisting}

\item
参见19.3.2节了解实现细节。
\end{itemize}

\textbf{std::add\_lvalue\_reference<T>::type}

\textbf{std::add\_rvalue\_reference<T>::type}

\begin{itemize}
\item
若T是可引用类型，则生成对T的左值或右值引用。

\item
若T不是可引用的(cv限定的)void或用const、volatile、\&和/或\&\&限定的函数类型)，则生成T。

\item
若T已经是一个引用类型，特性使用引用折叠规则(参见第15.6.1节):只有当使用add\_rvalue\_reference并且T是一个右值引用时，结果是一个右值引用。

\item
例如:
\begin{lstlisting}[style=styleCXX]
add_lvalue_reference_t<int> // yields int&
add_rvalue_reference_t<int> // yields int&&
add_rvalue_reference_t<int const> // yields int const&&
add_lvalue_reference_t<int const&> // yields int const&
add_rvalue_reference_t<int const&> // yields int const& (reference collapsing rules)
add_rvalue_reference_t<remove_reference_t<int const&>> // yields int&&
add_lvalue_reference_t<void> // yields void
add_rvalue_reference_t<void> // yields void
\end{lstlisting}

\item
参见第19.3.2节了解实现细节。
\end{itemize}

\textbf{std::remove\_pointer<T>::type}

\begin{itemize}
\item
生成指针类型T所指向的类型(若不是指针类型，则生成T本身)。

\item
例如:
\begin{lstlisting}[style=styleCXX]
remove_pointer_t<int> // yields int
remove_pointer_t<int const*> // yields int const
remove_pointer_t<int const* const* const> // yields int const* const
\end{lstlisting}
\end{itemize}

\textbf{std::add\_pointer<T>::type}

\begin{itemize}
\item
生成指向T的指针的类型，或在引用类型T的情况下，生成指向T基础类型的指针的类型。

\item
若没有这种类型，则生成T(适用于cv限定的函数类型)。

\item
例如:
\begin{lstlisting}[style=styleCXX]
add_pointer_t<void> // yields void*
add_pointer_t<int const* const> // yields int const* const*
add_pointer_t<int&> // yields int*
add_pointer_t<int[3]> // yields int(*)[3]
add_pointer_t<void(&)(int)> // yields void(*)(int)
add_pointer_t<void(int)> // yields void(*)(int)
add_pointer_t<void(int) const> // yields void(int) const (no change)
\end{lstlisting}
\end{itemize}

\textbf{std::remove\_extent<T>::type}

\textbf{std::remove\_all\_extents<T>::type}

\begin{itemize}
\item
给定数组类型，remove\_extent生成直接元素类型(本身可以是数组类型)，而remove\_all\_extents剥离所有“数组层”来产生底层元素类型(因此不再是数组类型)。若T不是数组类型，则生成T本身。

\item
指针没有维度信息，数组类型中未指定的边界指定维度(用数组类型声明的函数参数没有实际的数组类型，而且std::array也不是数组类型。参见第D.2.1节)。

\item
例如:
\begin{lstlisting}[style=styleCXX]
remove_extent_t<int> // yields int
remove_extent_t<int[10]> // yields int
remove_extent_t<int[5][10]> // yields int[10]
remove_extent_t<int[][10]> // yields int[10]
remove_extent_t<int*> // yields int*
remove_all_extents_t<int> // yields int
remove_all_extents_t<int[10]> // yields int
remove_all_extents_t<int[5][10]> // yields int
remove_all_extents_t<int[][10]> // yields int
remove_all_extents_t<int(*)[5]> // yields int(*)[5]
\end{lstlisting}

\item
参见第23.1.2节了解实现细节。
\end{itemize}

\textbf{std::decay<T>::type}

\begin{itemize}
\item
生成衰变的T。

\item
对于T类型执行以下转换:

\begin{itemize}
\item[-]
首先，使用remove\_reference(参见D.4)。

\item[-]
若结果是数组类型，则生成指向直接元素类型的指针(参见第7.1节)。

\item[-]
若结果是一个函数类型，则生成该函数类型的add\_pointer产生的类型(参见第11.1.1节)。

\item[-]
生成的结果不包含const/volatile限定符。
\end{itemize}

\item
初始化auto类型的对象时，通过参数的值传递或类型转换decay<>模型。

\item
decay<>对于处理可能用引用类型替代，但用于确定另一个函数的返回类型或参数类型的模板参数特别有用。关于讨论和使用std::decay<>()(历史上有用后者来实现std::make\_pair<>())的例子，请参阅第1.3.2节和第7.6节。

\item
例如:
\begin{lstlisting}[style=styleCXX]
decay_t<int const&> // yields int
decay_t<int const[4]> // yields int const*
void foo();
decay_t<decltype(foo)> // yields void(*)()
\end{lstlisting}

\item
参见19.3.2节了解实现细节。
\end{itemize}















